#include "board.h"
#include <QMouseEvent>
#include <QMessageBox>


Board::Board(QWidget *parent) : QWidget(parent)
{
    d = 36; r = d >> 1; //d:棋子直径 r:棋子半径
    init();
}

void Board::init()
{
    for (int i = 0; i < 32; i++)
        stones[i].init(i);
    isRedTurn = true;
    selectId = -1;
}

void Board::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //画10条横线
    for (int i = 1; i <= 10; i++)
        painter.drawLine(QPoint(d, d*i), QPoint(d*9, d*i));//9条竖线
    //画两边界竖线
    painter.drawLine(QPoint(d, d), QPoint(d, d*10));
    painter.drawLine(QPoint(d*9, d), QPoint(d*9, d*10));
    //画中间7条竖线
    for (int i = 2; i < 9; i++) {
        painter.drawLine(QPoint(d*i, d), QPoint(d*i, d*5));
        painter.drawLine(QPoint(d*i, d*6), QPoint(d*i, d*10));
    }
    //画九宫斜线
    painter.drawLine(QPoint(d*4, d), QPoint(d*6, d*3));
    painter.drawLine(QPoint(d*4, d*3), QPoint(d*6, d));
    painter.drawLine(QPoint(d*4, d*8), QPoint(d*6, d*10));
    painter.drawLine(QPoint(d*4, d*10), QPoint(d*6, d*8));
    //画棋子
    painter.setBrush(Qt::yellow);
    for (int i = 0; i < 32; i++)
        if(stones[i].isAlive){
            if (i == selectId)
                painter.setPen(Qt::gray);
            else
                painter.setPen(stones[i].red ? Qt::red : Qt::black);
            painter.drawEllipse(QPoint(d * stones[i].col, d * stones[i].row), r, r);
            painter.setFont(QFont("system", r, 700));
            painter.drawText(QRect(d*stones[i].col-r, d*stones[i].row-r, d, d), stones[i].getText(), QTextOption(Qt::AlignCenter));
        }
}

void Board::mouseReleaseEvent(QMouseEvent *event)
{
    int clickRow = (event->pos().y()+r)/d, clickCol = (event->pos().x()+r)/d;
    if (clickRow < 1 || clickRow > 10 || clickCol < 1 || clickCol > 9)
        return;
    clickHandler(getStoneId(clickRow, clickCol), clickRow, clickCol);
    update();
}

//判断该行列位置有没没棋子，有就返回ID，没有就返回-1
int Board::getStoneId(int row, int col)
{
    for (int i = 0; i < 32; i++)
        if (row == stones[i].row && col == stones[i].col && stones[i].isAlive)
            return i; //有棋子，返回棋子ID
    return -1; //该行列位置没棋子
}

void Board::clickHandler(int clickId, int row, int col)
{
    if (-1 == selectId && clickId >= 0 && stones[clickId].red == isRedTurn) //没选过棋子，选择棋子
        selectId = clickId;
    else if (selectId >= 0) { //已经选中过了棋子
        if (clickId >= 0) { //点的是子
            if (stones[clickId].red != stones[selectId].red && canMove(selectId, row, col)) { //是对方棋子，且可走，吃子
                saveStep(selectId, row, col, clickId);
                stones[clickId].isAlive = false;
                moveStone(selectId, row, col);
                selectId = -1;
                checkWin();
            } else if (stones[clickId].red == stones[selectId].red) //是己方棋子，不需判断是否可走，无条件切换
                selectId = clickId;
        } else if (canMove(selectId, row, col)) { //点空位，且可走
            saveStep(selectId, row, col, clickId);
            moveStone(selectId, row, col);
            selectId = -1;
        }
    }
}

bool Board::canMove(int id, int row, int col)
{
    switch (stones[id].type) {
    case Stone::KING:
        if (col > 3 && col < 7 &&
            ((stones[id].red && row < 4 || !stones[id].red && row > 7) && (abs(row - stones[id].row) + abs(col - stones[id].col) == 1)) //0+1=1
            || countAtLine(stones[4].row, stones[4].col, stones[20].row, stones[20].col) == 0)
            return true;
        break;
    case Stone::CHE:
        if (countAtLine(row, col, stones[id].row, stones[id].col) == 0)
            return true;
        break;
    case Stone::MA:
        if ( (abs(row-stones[id].row)==1 && abs(col-stones[id].col)==2 //左右跳
             && getStoneId(stones[id].row,(col+stones[id].col)>>1) == -1 //没拐脚
             ) || (abs(row-stones[id].row)==2 && abs(col-stones[id].col)==1 //上下跳
                   && getStoneId((row+stones[id].row)>>1,stones[id].col) == -1)) //没拐脚
            return true;
        break;
    case Stone::PAO:
        if (getStoneId(row, col) == -1 && countAtLine(row, col, stones[id].row, stones[id].col) == 0 //移动
            || getStoneId(row, col) != -1 && countAtLine(row, col, stones[id].row, stones[id].col) == 1) //吃子
            return true;
        break;
    case Stone::XIANG:
        if ((stones[id].red && row < 6 || !stones[id].red && row > 5) //没过河
            && abs(row - stones[id].row) == 2 && abs(col - stones[id].col) == 2 //象步
            && getStoneId((row+stones[id].row)>>1, (col+stones[id].col)>>1) == -1 ) //没象眼
            return true;
        break;
    case Stone::SHI:
        if (col > 3 && col < 7 && (stones[id].red && row < 4 || !stones[id].red && row > 7)
            && abs(row - stones[id].row) == 1 && abs(col - stones[id].col) == 1)
            return true;
        break;
    case Stone::BING:
        if (abs(row - stones[id].row) + abs(col - stones[id].col) != 1)
            break;
        if (stones[id].red) { //红棋在上
            if (row < stones[id].row) break;
            if (stones[id].row < 6 && row == stones[id].row) break;
        } else { //黑棋在下
            if (row > stones[id].row) break;
            if (stones[id].row > 5 && row == stones[id].row) break;
        }
        return true;
    }
    return false;
}

//统计直线上棋子个数
int Board::countAtLine(int row1, int col1, int row2, int col2)
{
    int min, max, cnt = 0;
    if (row1 != row2 && col1 != col2)
        return -1;
    if (row1 == row2) {
        if (col1 < col2) {
            min = col1;
            max = col2;
        } else {
            min = col2;
            max = col1;
        }
        for (int col = min+1; col < max; col++)
            if (getStoneId(row1, col) >= 0)
                cnt++;
    } else if (col1 == col2) {
        if (row1 < row2) {
            min = row1;
            max = row2;
        } else {
            min = row2;
            max = row1;
        }
        for (int row = min+1; row < max; row++)
            if (getStoneId(row, col1) >= 0)
                cnt++;
    }
    return cnt;
}

void Board::moveStone(int id, int row, int col)
{
    stones[id].row = row;
    stones[id].col = col;
//    selectId = -1;
    isRedTurn = !isRedTurn;
}

void Board::saveStep(int fromId, int rowTo, int colTo, int targetId)
{
    Step *step = new Step;
    step->rowFrom = stones[fromId].row;
    step->colFrom = stones[fromId].col;
    step->rowTo = rowTo;
    step->colTo = colTo;
    step->fromId = fromId;
    step->toId = targetId;
    steps.append(step);
}

void Board::checkWin()
{
    if (!stones[4].isAlive) {
        QMessageBox::information(this, "结束啦", "黑胜");
        steps.clear();
        init();
    } else if (!stones[20].isAlive) {
        QMessageBox::information(this, "结束啦", "红胜");
        steps.clear();
        init();
    }
}
void Board::backOne()
{
    if(steps.size() == 0) return;

    Step* step = steps.last();

    if (step->toId >= 0)
        stones[step->toId].isAlive = true;
    moveStone(step->fromId, step->rowFrom, step->colFrom);

    steps.removeLast();

    update();
    delete step;
}

void Board::slotBack()
{
    backOne();
    backOne();
}
